package org.gwtEss.table.pages;

import java.util.ArrayList;

import org.gwtEss.link.LabelLink;

import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Widget;

public abstract class DefaultPageNavigator extends Composite implements NavigationWidget  {
	private int pageNum = -1;
	private int rowsPerPage = 0, dataListSize = 0;
	private HorizontalPanel hPanel;
	private ListBox pageLst;
	private SelectPageLink firstPageLink, prevPageLink, nextPageLink, lastPageLink;
	public void setSelectedPage(int selectPageNum){
		if (!initialized) throw new RuntimeException("You should use the render method before setting a selected page. ");
		int lastPageNum = calculateLastPageNum();
		if ((selectPageNum > 0) && (selectPageNum <= lastPageNum)){
			pageNum = selectPageNum;
			boolean isFistPage = (pageNum==1); 
			boolean isLastPage = lastPageNum == pageNum; 
			prevPageLink.setEnabled(!isFistPage);
			firstPageLink.setEnabled(!isFistPage);
			nextPageLink.setEnabled(!isLastPage);
			lastPageLink.setEnabled(!isLastPage);
			if ((pageNum-1) != pageLst.getSelectedIndex())
				pageLst.setSelectedIndex(pageNum-1);
		}
		
	}
	private int calculateLastPageNum(){
		return calculateLastPageNum(dataListSize, rowsPerPage);
	}
	private int calculateLastPageNum(int dataListSize, int rowsPerPage){
		if (rowsPerPage < 1) return 0; 
		return (int)Math.round(((float)dataListSize/rowsPerPage) + 0.4);
	}
	private void firePageSelect(int newPage){
		setSelectedPage(newPage);
//		listeners.firePageSelect((pageNum-1)*rowsPerPage, (pageNum-1)*rowsPerPage + rowsPerPage, pageNum);
		onPageSelect((pageNum-1)*rowsPerPage, (pageNum-1)*rowsPerPage + rowsPerPage, pageNum);
	}

	public DefaultPageNavigator() {
		initWidget(hPanel = new HorizontalPanel());	
	}
	private void init(){
		pageLst = new ListBox(false){
			{
				addChangeListener(new ChangeListener() {
				
					public void onChange(Widget sender) {
						int newPage = ((ListBox)pageLst).getSelectedIndex() + 1;
						firePageSelect(newPage);
//						firePageSelect();
					}
				});
			}
		};
		firstPageLink = new SelectPageLink("<<", new ClickListener(){
			public void onClick(Widget sender) {
//				pageNum = 1;
//				firePageSelect();
				firePageSelect(1);
			}
			
		});
		prevPageLink = new SelectPageLink("<", new ClickListener(){

			public void onClick(Widget sender) {
//				--pageNum;
//				firePageSelect();
				firePageSelect(--pageNum);
			}
			
		});
		nextPageLink = new SelectPageLink(">", new ClickListener(){

			public void onClick(Widget sender) {
//				
//				pageNum++;
//				firePageSelect();
				firePageSelect(++pageNum);
			}
			
		});
		lastPageLink = new SelectPageLink(">>", new ClickListener(){

			public void onClick(Widget sender) {
//				pageNum=lastPageNum;
//				firePageSelect();
				
				firePageSelect(calculateLastPageNum());
			}
			
		});
		hPanel.add(firstPageLink);
		hPanel.add(new HTML("&nbsp;"));
		hPanel.add(prevPageLink);
		hPanel.add(new HTML("&nbsp;"));
		hPanel.add(pageLst);
		hPanel.add(new HTML("&nbsp;"));
		hPanel.add(nextPageLink);
		hPanel.add(new HTML("&nbsp;"));
		hPanel.add(lastPageLink);
		initialized = true;
	}
	/*public DefaultPageNavigator(PageNavigatorListener listener) {
		addPagesListener(listener);
	}*/

	private boolean initialized = false;
	public void render(int rowsPerPage, int dataListSize) {
		if (!initialized) init();
		if (rowsPerPage < 1) throw new RuntimeException("Invalid rows per page");
		if (this.dataListSize != dataListSize){
			int oldLastPage = calculateLastPageNum();
			int newLastPage = calculateLastPageNum(dataListSize, rowsPerPage);
			if (oldLastPage < newLastPage){
				for (int i=oldLastPage; i<newLastPage; i++)
					pageLst.addItem(String.valueOf(i+1), String.valueOf(i+1));			
			}else if (oldLastPage > newLastPage){
				for (int i=newLastPage; i<oldLastPage; i--)
					pageLst.removeItem(i);
			}
			pageNum = pageNum == -1?1:pageNum;
			this.dataListSize = dataListSize; 
			this.rowsPerPage = rowsPerPage;
//			int lastPageNum = calculateLastPageNum();//(int)Math.round(((float)dataListSize/rowsPerPage) + 0.4);
//			pageLst.clear();
//			if (pageNum )
//			pageNum = 1; 
			
 
			prevPageLink.setEnabled(false);
			firstPageLink.setEnabled(false);
			nextPageLink.setEnabled(true);
			lastPageLink.setEnabled(true);
		}

	}
	
	private class SelectPageLink extends LabelLink{

		public SelectPageLink(String text, ClickListener clickListener) {
			super();
			setText(text);
//			setTargetHistoryToken(text);
			addClickListener(clickListener);
		}
	}
/*	PageNavigatorListenerCollection listeners = new PageNavigatorListenerCollection();
	public class PageNavigatorListenerCollection extends ArrayList<PageNavigatorListener>{
		public void firePageSelect(int startRow, int endRow, int pageNum){
			for (PageNavigatorListener listener: this)
				listener.onPageSelect(DefaultPageNavigator.this, startRow, endRow, pageNum);
		}
	}
	public void addPagesListener(PageNavigatorListener listener) {
		listeners.add(listener);
	}
	public void removePagesListener(PageNavigatorListener listener) {
		listeners.remove(listener);
	}
*/	public void setEnabled(boolean enabled) {
		if (!initialized) init();
		pageLst.setEnabled(enabled);
		firstPageLink.setEnabled(enabled);
		lastPageLink.setEnabled(enabled);
		nextPageLink.setEnabled(enabled);
		prevPageLink.setEnabled(enabled);
	}
	public void renderAndSelect(int rowsPerPage, int dataListSize, int pageNum) {
		render(rowsPerPage, dataListSize);
		setSelectedPage(pageNum);
	}
	public abstract void onPageSelect(int startRow, int endRow,
			int pageNum);
}
